#include <cellcsp.h>
#include <string>
#include <stdio.h>
#include <csp_debug.h>
#include <ProcessStats.h>
#include <vector>

int main(){


	char *fact_file                   = "./tasks/fact_task";
	char *fact_yield_calleesaves_file = "./tasks/fact_yield_calleesaves_task";
	char *fact_yield_file             = "./tasks/fact_yield_task";
	char *get_runtime_info_file       = "./tasks/get_runtime_info_task";
	char *get_runtime_info_yield_file = "./tasks/get_runtime_info_yield_task";
	char *globalvars_file             = "./tasks/globalvars_task";
	char *globalvars_yield_file       = "./tasks/globalvars_yield_task";
	char *init_yield_file             = "./tasks/init_yield_task";
	char *mergesort_file              = "./tasks/mergesort_task";    
	char *quicksort_file              = "./tasks/quicksort_task";      

	
	CSPConfig conf;

	conf.add_csp_program(fact_file                  ,"fact_task");                  
	conf.add_csp_program(fact_yield_calleesaves_file,"fact_yield_calleesaves_task");
	conf.add_csp_program(fact_yield_file            ,"fact_yield_task");            
	conf.add_csp_program(get_runtime_info_file      ,"get_runtime_info_task");      
	conf.add_csp_program(get_runtime_info_yield_file,"get_runtime_info_yield_task");
	conf.add_csp_program(globalvars_file            ,"globalvars_task");            
	conf.add_csp_program(globalvars_yield_file      ,"globalvars_yield_task");      
	conf.add_csp_program(init_yield_file            ,"init_yield_task");            
	conf.add_csp_program(mergesort_file             ,"mergesort_task");             
	conf.add_csp_program(quicksort_file             ,"quicksort_task");             


	CellCSP_start(conf);

	printf("Running yield_test with file %s\n", fact_file);                  
	printf("Running yield_test with file %s\n", fact_yield_calleesaves_file); /*
	printf("Running yield_test with file %s\n", fact_yield_file);            
	printf("Running yield_test with file %s\n", get_runtime_info_file);      
	printf("Running yield_test with file %s\n", get_runtime_info_yield_file);
	printf("Running yield_test with file %s\n", globalvars_file);            
	printf("Running yield_test with file %s\n", globalvars_yield_file);      
	printf("Running yield_test with file %s\n", init_yield_file);            
	printf("Running yield_test with file %s\n", mergesort_file);*/
	printf("Running yield_test with file %s\n", quicksort_file);             

	ProcessStats* stats = ProcessStats::Instance();	

	#define QUICKSORT_RES 3399
	#define FACT_RES 3628800
	#define FACT_YIELD_CALLEE_RES 120
	#define FACT_YIELD_RES 132
	#define RUNTIME_NFO_RES 65902
	#define RUNTIME_NFO_YIELD_RES 632954
	#define GLOBAL_VARS_RES (120+69)
	#define GLOBAL_VARS_YIELD_RES (120+721)
	#define INIT_YIELD_RES 6712
	#define MERGESORT_RES 88732
	

	CSPProcess yield0("quicksort_task");
	stats->RegisterExpectedRes(yield0.GetProcessComposition(), QUICKSORT_RES);

	Parallel par( &yield0, NULL) ; 

	unsigned int i;
	CSPProcess *p;
	for(i=0; i < 500; i++){
		p = new CSPProcess("fact_task");     
		par.Add(p);
		stats->RegisterExpectedRes(p->GetProcessComposition(), FACT_RES);
		p = new CSPProcess("fact_yield_calleesaves_task");
		par.Add(p);
		stats->RegisterExpectedRes(p->GetProcessComposition(), FACT_YIELD_CALLEE_RES);
		p = new CSPProcess("fact_yield_task");            
		par.Add(p);
		stats->RegisterExpectedRes(p->GetProcessComposition(), FACT_YIELD_RES);
		p = new CSPProcess("get_runtime_info_task");      
		par.Add(p);
		stats->RegisterExpectedRes(p->GetProcessComposition(), RUNTIME_NFO_RES);
		p = new CSPProcess("get_runtime_info_yield_task");
		par.Add(p);
		stats->RegisterExpectedRes(p->GetProcessComposition(), RUNTIME_NFO_YIELD_RES);
		p = new CSPProcess("globalvars_task");            
		par.Add(p);
		stats->RegisterExpectedRes(p->GetProcessComposition(), GLOBAL_VARS_RES);
		p = new CSPProcess("globalvars_yield_task");      
		par.Add(p);
		stats->RegisterExpectedRes(p->GetProcessComposition(), GLOBAL_VARS_YIELD_RES);
		p = new CSPProcess("init_yield_task");            
		par.Add(p);
		stats->RegisterExpectedRes(p->GetProcessComposition(), INIT_YIELD_RES);
		p = new CSPProcess("mergesort_task");             
		par.Add(p);
		stats->RegisterExpectedRes(p->GetProcessComposition(), MERGESORT_RES);
		p = new CSPProcess("quicksort_task");
		par.Add(p);
		stats->RegisterExpectedRes(p->GetProcessComposition(), QUICKSORT_RES);
	}

	int n_procs = 1+i*10;
	stats->SetExpectedTerminatedProcesses(n_procs);
	printf("par.Run() with %i processes.\n", n_procs);
	par.Run();
	

	CellCSP_end();

	vector<CSPProcess*> *procs = par.GetProcs();
	printf("%i terminated processes.\n", (int) procs->size());
	for(i=0; i < procs->size(); i++){
		//CSPProcess *p = procs->at(i);
		//printf("Process with pid %i terminated with status %i\n", p->GetPID(), p->GetExitStatus());	
	}

	stats->Check();

	printf("yield_test terminated\n");
	
	return 0;
}
